//////////////////////////////////////////
// 智龙LCD和温湿度项目温湿度AM2320模块驱动
// 作者：zz                               
// Email:90807@QQ.com
// 本软件免费开源，修改请保留作者信息，谢谢
/////////////////////////////////////////

#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>

struct class *cls;

//设备结构体
struct i2c_client *client;
struct i2c_board_info info;
unsigned short addrs[]={(0xb8>>1),I2C_CLIENT_END};

int read_i2c(char *data);

ssize_t open(struct inode *ind,struct file *fl)
{
  return 0;
}

ssize_t read(struct file *fl,char __user *buf,size_t len,loff_t *off)
{
  unsigned char data[7];
  memset(data,0,sizeof(data));
  while(data[0]==0x00)
  {
  read_i2c(data); 
  //printk("AM2320 probe  RH:%d |  temper: %d\n",(data[2]<<8)+data[3],(data[4]<<8)+data[5]);
  }
  buf[0]=data[2];
  buf[1]=data[3];
  buf[2]=data[4];
  buf[3]=data[5];
  return 4;
}

struct file_operations fops={
				.owner=THIS_MODULE,
        .read=read,
        .open=open,
};

int probe(struct i2c_client *client,const struct i2c_device_id *id)
{
  int ret;
  unsigned char data[7];
  memset(data,0,sizeof(data));

  ret=register_chrdev(232,"AM2320",&fops);
  cls=class_create(THIS_MODULE,"am2320_cls");
  device_create(cls,NULL,MKDEV(232,0),NULL,"AM2320"); //创建设备节点
  read_i2c(data); 
  printk("AM2320 probe  RH:%d |  temper: %d\n",(data[2]<<8)+data[3],(data[4]<<8)+data[5]);
  printk("Power by ZZ\n");
  printk("Email:90807@QQ.COM\n");
  printk("ZZ:Init Lcd serial\n");
  printk("%x\n",*((int *)0xbfd011d8));
  *(int *)0xbfd011d8 |=1<<13;
  *(int *)0xbfd011d8 |=1<<14;
  printk("%x\n",*((int *)0xbfd011d8));

  return ret;
}

int read_i2c(char *data)
{ 
  unsigned char getversion[]={0x03,0x00,0x04};
  struct i2c_msg cmd[2];
  cmd[0].addr = client->addr;
  cmd[0].flags=0; //write
  cmd[0].len=4;
  cmd[0].buf=getversion;
  i2c_transfer(client->adapter,&cmd[0],1);
  mdelay(200);
 
  //cmd 1 为读数据
  cmd[1].addr = client->addr;
  cmd[1].flags =1;
  cmd[1].len=6;
  cmd[1].buf=data;
  i2c_transfer(client->adapter,&cmd[1],1);
  return 0;
}
  


int remove(struct i2c_client *client)
{
  printk("zz : am2320 remove...\n");
  device_destroy(cls,MKDEV(232,0));
  class_destroy(cls);
  unregister_chrdev(232,"ama2320");
  return 0;
}

struct i2c_device_id ids[]={
				{"am2320"},
        {},
};

//驱动结构体
struct i2c_driver am2320_drv={
        .probe=probe,
        .remove=remove,
        .id_table=ids,
        .driver={
           .name="am2320",
       },
};


static int __init am2320_init(void)
{
  struct i2c_adapter *adapter;

  memset(&info,0,sizeof(info));
  strcpy(info.type,"am2320");
  adapter = i2c_get_adapter(0);
  client = i2c_new_probed_device(adapter,&info,addrs,NULL);
  i2c_put_adapter(adapter);
  return i2c_add_driver(&am2320_drv);
}

static void __exit am2320_exit(void)
{
   i2c_del_driver(&am2320_drv);
   i2c_unregister_device(client);
}


module_init(am2320_init);
module_exit(am2320_exit);
MODULE_LICENSE("GPL");
